#include<stdlib.h>
#include<stdio.h>
// this file is translating from the tabu_for_graph_color.py file. So please refering tabu_for_graph_color.py for comment

int find_neighbors(int neighbors[][3],int node_num,int color_num,int solution_1[],int solution_2[]){
    int *n_1 = (int *)malloc(300*sizeof(int));
    int *n_2 = (int *)malloc(300*sizeof(int));
    int *n_3 = (int *)malloc(300*sizeof(int));
    int s,i_1,i_2,i_3;
    s = i_1 = i_2 = i_3 = 0;

    for(int i=0; i<node_num; i++){
        if(solution_1[i*color_num+solution_2[i]] <= 0){continue;}
        for(int j=0; j<color_num; j++){
            if(j == solution_2[i]){continue;}
            if(solution_1[i*color_num+j] <= 0){
                if(i_1>=100){goto out;}
                n_1[3*i_1] = i;
                n_1[3*i_1+1] = solution_2[i];
                n_1[3*i_1+2] = j;
                i_1++;
                continue;
            }
            if(solution_1[i*color_num+j] <= solution_1[i*color_num+solution_2[i]]){
                if(i_2>=100){continue;}
                n_2[3*i_2] = i;
                n_2[3*i_2+1] = solution_2[i];
                n_2[3*i_2+2] = j;
                i_2++;
                continue;
            }
            if(i_3>=100){continue;}
            n_3[3*i_3] = i;
            n_3[3*i_3+1] = solution_2[i];
            n_3[3*i_3+2] = j;
            i_3++;
        }
    }
    out:
    for(int i=0; i<i_1; i++){
        neighbors[s][0] = n_1[3*i+0];
        neighbors[s][1] = n_1[3*i+1];
        neighbors[s++][2] = n_1[3*i+2];
    }
    for(int i=0; i<i_2; i++){
        if(s >= 100){
            free(n_1);
            free(n_2);
            free(n_3);
            return s;
        }
        neighbors[s][0] = n_2[3*i+0];
        neighbors[s][1] = n_2[3*i+1];
        neighbors[s++][2] = n_2[3*i+2];
    }
    for(int i=0; i<i_3; i++){
        if(s >= 100){
            free(n_1);
            free(n_2);
            free(n_3);
            return s;
        }
        neighbors[s][0] = n_3[3*i+0];
        neighbors[s][1] = n_3[3*i+1];
        neighbors[s++][2] = n_3[3*i+2];
    }
    free(n_1);
    free(n_2);
    free(n_3);
    return s;
}
int eval_solution(int move[],int node_num,int color_num,int solution_1[], int solution_2[],int graph[]){
    int val = 0;
    val += solution_1[move[0]*color_num+move[1]];
    val -= solution_1[move[0]*color_num+move[2]];
    for(int i=0; i<node_num; i++){
        if(graph[move[0]*node_num+i] < 1){continue;}
        if(solution_2[i] == move[1]){val += 1;continue;}
        if(solution_2[i] == move[2]){val -= 1;}
    }
    return val;
}
int pick_solution(int move[],int neighbors[][3],int node_num, int color_num,int solution_1[],int solution_2[],int graph[],int neighbors_num,int first_n,int tabu_list[][2],int tabu_length,int candidates_num){

    int *candidates = (int *)malloc(4*candidates_num*sizeof(int));

    for(int i=0; i<neighbors_num; i++){
        int j = neighbors[i][0];
        int c1 = neighbors[i][1];
        int c2 = neighbors[i][2];
        int val = 0;
        // eval solutioin
        val += solution_1[j*color_num+c1];
        val -= solution_1[j*color_num+c2];
        for(int k=0; k<node_num; k++){
            if(graph[j*node_num+k] < 1){continue;}
            if(solution_2[k] == c1){val += 1;continue;}
            if(solution_2[k] == c2){val -= 1;}
        }

        candidates[4*i+0] = j;
        candidates[4*i+1] = c1;
        candidates[4*i+2] = c2;
        candidates[4*i+3] = val;
    }

    int *index = (int *)malloc(first_n*sizeof(int));
    for(int i=0; i<first_n; i++){
        index[i] = 0;
        int val = candidates[3];
        for(int j=1; j<neighbors_num; j++){
            if(candidates[4*j+3] > val){
                index[i] = j;
                val = candidates[4*j+3];
            }
        }
        candidates[4*index[i]+3] -= 100; // this is small enough for it to scape the next iteration
    }

    int check;
    if(candidates[4*index[0]+3] <= 0){
        check = 1;
    }else{
        check = 0;
    }

    for(int i=0; i<first_n; i++){
        int in_tabu = 0;
        for(int j=0; j<tabu_length; j++){
            if(candidates[4*index[i]+0] == tabu_list[j][0] &&
                    candidates[4*index[i]+2] == tabu_list[j][1]){
                in_tabu = 1;
                break;
            }
        }
        if(in_tabu == 0){
            move[0] = candidates[4*index[i]+0];
            move[1] = candidates[4*index[i]+1];
            move[2] = candidates[4*index[i]+2];
            free(candidates);
            free(index);
            return check;
        }
    }
    return check;
}




        

